/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gvscanreader;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author robertobertolotti
 * @author alessandrobertolini
 */
public class Procedure 
{
    
    public class Link
    {
        public int sub1, sub2;
        
        public Link()
        {
            
        }
    };
    
    // Parametri esterni
    String nomeDbInput = "eneldebug";
    //String nomeDbOutput = "vulsim_schema";
    String utente = "root";
    String psw = "robeertoo";
    String nomeSistema = "Enel";
    String descrizioneSistema = "Sistema Enel";
    String obiettivo = "'net info 172.16.15.35-'"; // Enel idroattivo
    //String obiettivo = "'net info 172.16.10.1-'"; // Enel normale
    //String obiettivo = "'admin 100.1.1.83-'"; // Selex
    String[] minacceAccess = {"192.168.8.103"}; // mettere nome host oppure "all" oppure "empty"
    String[] minacceAdmin = {"all"}; // mettere nome host oppure "all" oppure "empty"
    
    DBConnector dbconEnel;
    DBConnector dbconVulsim;
    ArrayList enelVuln=null;
    ArrayList enelRights=null;
    String[] specialHost;
    String[] specialInterface;
    
    ArrayList <String> dirittiList;//lista dei possibili diritti
    ArrayList <String> hostDirittiList;//lista degli host che possiedono i diritti
    
    private ArrayList <String> oldWords;
    private ArrayList <String> newWords;
    
    
    public Procedure()
    {
        dbconEnel = new DBConnector( nomeDbInput, utente, psw );
        dbconEnel.connect();
        dbconVulsim = new DBConnector( "vulsim_schema", utente, psw );
        dbconVulsim.connect();
        
        dirittiList = new ArrayList<String>();
        hostDirittiList = new ArrayList <String>();
        oldWords = new ArrayList <String>();
        newWords = new ArrayList <String>();
        oldWords.add("10.0.255.101");
        newWords.add("Switch 1");
        oldWords.add("10.0.255.162");
        newWords.add("Staz. Controllo 2");
        oldWords.add("10.0.255.163");
        newWords.add("Staz. Ingegneria 1");
        oldWords.add("10.0.255.165");
        newWords.add("ASC");
        oldWords.add("10.0.255.171");
        newWords.add("Client Scada 1");
        oldWords.add("10.0.255.1");
        newWords.add("Staz. Controllo 1");
        oldWords.add("10.0.255.201");
        newWords.add("Switch 2");
        oldWords.add("10.0.255.210");
        newWords.add("Firewall Frontiera Proc.,Intranet");
        oldWords.add("10.0.255.212");
        newWords.add("Firewall 1");
        oldWords.add("10.0.255.231");
        newWords.add("Stampante 1");
        oldWords.add("10.0.255.232");
        newWords.add("Stampante 2");
        oldWords.add("10.0.255.237");
        newWords.add("Client Scada 2");
        oldWords.add("10.0.255.239");
        newWords.add("Firewall 2");
        oldWords.add("10.0.255.2");
        newWords.add("Staz. Controllo 3");
        oldWords.add("10.0.255.3");
        newWords.add("Staz. Controllo 4");
        oldWords.add("10.0.255.4");
        newWords.add("Staz. Controllo 5");
        oldWords.add("10.0.255.5");
        newWords.add("Staz. Ingegneria 2");
        oldWords.add("172.16.10.1");
        newWords.add("PLC1");
        oldWords.add("172.16.10.229");
        newWords.add("Router 1");
        oldWords.add("172.16.10.230");
        newWords.add("Router 2");
        oldWords.add("172.16.10.231");
        newWords.add("Access Point 1");
        oldWords.add("172.16.10.232");
        newWords.add("Access Point 2");
        oldWords.add("172.16.10.238");
        newWords.add("Access Point 3");
        oldWords.add("172.16.10.2");
        newWords.add("PLC2");
        oldWords.add("172.16.10.55");
        newWords.add("Switch 3");
        oldWords.add("172.16.10.5");
        newWords.add("Switch 4");
        oldWords.add("192.168.8.103");
        newWords.add("Client Telecontrollo 1");
        oldWords.add("192.168.8.104");
        newWords.add("Client Telecontrollo 2");
        oldWords.add("192.168.8.10");
        newWords.add("Firewall Frontiera Intranet,Proc.");
        oldWords.add("192.168.8.1");
        newWords.add("Switch 5");
        oldWords.add("192.168.8.30");
        newWords.add("Parent Server Antivirus");
        oldWords.add("192.168.8.32");
        newWords.add("Access Point 4");
    }
    
    public void sostituisci()
    {
        ArrayList r = null;
        boolean b;
        // Carica gli host presenti nella tabella enel.host...
        try
        {
            r = dbconVulsim.query( "componente", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String nome = rimpiazzaWord( ss[1] );
            System.out.println("UPDATE `vulsim_schema`.`componente` SET `nome`='"
                             + nome + "', `descrizione`='"
                             + nome + "' WHERE `idComponente`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`componente`", "`nome`", "'" + nome + "'", "`idComponente`='" + id + "'" );
                b = dbconVulsim.update( "`componente`", "`descrizione`", "'" + nome + "'", "`idComponente`='" + id + "'" );
            } catch (SQLException ex) {}
        }
        try
        {
            r = dbconVulsim.query( "attacco", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String nome = rimpiazzaWord( ss[1] );
            String pre = rimpiazzaWord( ss[3] );
            String post = rimpiazzaWord( ss[4] );
            System.out.println("UPDATE `vulsim_schema`.`attacco` SET `nome`='"
                             + nome + "', `precondizione`='"
                             + pre + "', `postcondizione`='"
                             + post + "' WHERE `id`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`attacco`", "`nome`", "'" + nome + "'", "`id`='" + id + "'" );
                b = dbconVulsim.update( "`attacco`", "`precondizione`", "'" + pre + "'", "`id`='" + id + "'" );
                b = dbconVulsim.update( "`attacco`", "`postcondizione`", "'" + post + "'", "`id`='" + id + "'" );
            } catch (SQLException ex) {}
        }
        try
        {
            r = dbconVulsim.query( "diritto", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String componente = rimpiazzaWord( ss[1] );
            String operazione = rimpiazzaWord( ss[2] );
            System.out.println("UPDATE `vulsim_schema`.`diritto` SET `componente`='"
                             + componente + "', `operazione`='"
                             + operazione + "' WHERE `id`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`diritto`", "`componente`", "'" + componente + "'", "`id`='" + id + "'" );
                b = dbconVulsim.update( "`diritto`", "`operazione`", "'" + operazione + "'", "`id`='" + id + "'" );
            } catch (SQLException ex) {}
        }
        try
        {
            r = dbconVulsim.query( "minaccia", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String dirittiIniziali = rimpiazzaWord( ss[3] );
            String nomeMinaccia = dirittiIniziali.substring( 0, dirittiIniziali.length() - 1 );
            nomeMinaccia = nomeMinaccia.substring(7);
            String nome = "min. " + nomeMinaccia;
            System.out.println("UPDATE `vulsim_schema`.`minaccia` SET `nome`='"
                             + nome + "', `dirittiIniziali`='"
                             + dirittiIniziali + "' WHERE `id`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`minaccia`", "`nome`", "'" + nome + "'", "`id`='" + id + "'" );
                b = dbconVulsim.update( "`minaccia`", "`dirittiIniziali`", "'" + dirittiIniziali + "'", "`id`='" + id + "'" );
            } catch (SQLException ex) {}
        }
        try
        {
            r = dbconVulsim.query( "obiettivo", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String nome = rimpiazzaWord( ss[1] );
            String diritti = rimpiazzaWord( ss[2] );
            System.out.println("UPDATE `vulsim_schema`.`obiettivo` SET `nome`='"
                             + nome + "', `diritti`='"
                             + diritti + "' WHERE `idObiettivo`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`obiettivo`", "`nome`", "'" + nome + "'", "`idObiettivo`='" + id + "'" );
                b = dbconVulsim.update( "`obiettivo`", "`diritti`", "'" + diritti + "'", "`idObiettivo`='" + id + "'" );
            } catch (SQLException ex) {}
        }
        try
        {
            r = dbconVulsim.query( "vulnerabilita", "*", null );
        } catch (SQLException ex) {}
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            String id = ss[0];
            String nome = rimpiazzaWord( ss[1] );
            System.out.println("UPDATE `vulsim_schema`.`vulnerabilita` SET `nome`='"
                             + nome + "' WHERE `idVulnerabilita`='" + id + "';");
            try
            {
                b = dbconVulsim.update( "`vulnerabilita`", "`nome`", "'" + nome + "'", "`idVulnerabilita`='" + id + "'" );
            } catch (SQLException ex) {}
        }
    }
    
    public String rimpiazzaWord(String oldWord)
    {
        //return oldWord;
        
        String newWord = oldWord;
        for ( int i = 0; i < oldWords.size(); i++ )
        {
            newWord = newWord.replaceAll( oldWords.get(i), newWords.get(i) );
        }
        return newWord;
    }
    
    // <editor-fold defaultstate="collapsed" desc="utility"> 
    
    private int translateStringToNum(String str){
        int id;
        try{
          id = Integer.parseInt(str);}
        catch(NumberFormatException e){
            return -1;
        }
        return id;
    }
    
    /**
     * Aggiunge gli apici alle stringhe
     * @param str
     * @return 
     */
    private String formatName(String str){
        if(str==null){
            int a=0;
            return null;
        }
        
        CharSequence str1 = "'";
        CharSequence str2 = " ";
        str = str.replace(str1, str2);
        return "'"+str+"'";
    }
    
    
    // </editor-fold> 

   
    
    
    // <editor-fold defaultstate="collapsed" desc="componenti"> 
    
    /**
     * Calcola i componenti e li inserisce nel db vulsim
     */
    public void elaboraComponenti()
    {
        ArrayList enelSpecialHost=null;
        // Scarica dai db enel e vulsim_schema 4 tabelle utili per la computazione
        try
        {
            enelSpecialHost = dbconEnel.query( "hostconnection", "host, interface", "host != interface" );
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        // Calcola due array di stringhe che hanno dentro di sè tutti quegli indirizzi ip non presenti in enel.host
        // e i relativi "indirizzi reali"
        specialHost = new String[enelSpecialHost.size()];
        specialInterface = new String[enelSpecialHost.size()];
        for ( int i = 0; i < enelSpecialHost.size(); i++ )
        {
            String[] sh = (String[])(enelSpecialHost.get(i));
            specialHost[i] = sh[0];
            specialInterface[i] = sh[1];
        }
          
        ArrayList r = null;
        // Carica gli host presenti nella tabella enel.host...
        try
        {
            r = dbconEnel.query( "host", "*", null );
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        // .. e li inserisce pari pari nella tabella componente di vulsim_schema con questa corrispondenza di campi:
        // enel.host.primaryIp -> vulsim_schema.componente.nome,
        // enel.host.name -> vulsim_schema.componente.descrizione
        for ( int i = 0; i < r.size(); i++ )
        {
            String[] ss = (String[])(r.get(i));
            insertDiritto( "access " + ss[0], ss[0] );
            insertDiritto( "admin " + ss[0], ss[0] );
            try
            {
                String campo, valore;
                campo = "idComponente, nome, descrizione, idSistema, subnet";
                valore = "'" + ( i + 1 ) + "' , '" + ss[0] + "' , '" + ss[1] + "' , '1', '" + ss[2] + "'";
                dbconVulsim.insert( "componente", campo, valore );
            } catch (SQLException ex) {return;}
        }
    }
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="attacchi"> 
    
    /**
     * Restituisce le postcondizioni dell'attacco dato il tipo di vulnerabilità che l'attacco sfrutta
     * e dato l'host che l'attacco insidia
     */
    private String getPostAtk(String vulnType, String host)
    {
        String res = "";
        boolean admin = false;
        
        // Per ogni tipologia di vulnerabilità/attacco si stabilisce se questi da o meno 
        // (tra le altre cose) diritti di admin e quali diritti l'attacco da
        if ( vulnType.compareTo( "ADMIN LOGIN GUESSABLE" ) == 0 )
        {
            admin = true;
            res = "admin " + host;
            //res = res + "-data disclosure " + host + "-dos " + host + "-info " + host + "-net info " + host + "-purge " + host + "-user " + host + "-local " + host + "-server info " + host + "-user enum " + host;
        }
        if ( vulnType.compareTo( "LOCAL PRIVILEGES ESCALATION" ) == 0 )
        {
            admin = true;
            res = "admin " + host;
            //res = res + "-data disclosure " + host + "-dos " + host + "-info " + host + "-net info " + host + "-purge " + host + "-user " + host + "-local " + host + "-server info " + host + "-user enum " + host;
        }
        if ( vulnType.compareTo( "MAN IN THE MIDDLE - GET ACCESS" ) == 0 )
        {
            admin = true;
            res = "admin " + host;
            //res = res + "-data disclosure " + host + "-dos " + host + "-info " + host + "-net info " + host + "-purge " + host + "-user " + host + "-local " + host + "-server info " + host + "-user enum " + host;
        }
        if ( vulnType.compareTo( "REMOTE CODE EXECUTION WITH ADMIN PRIVILEGES" ) == 0 )
        {
            admin = true;
            res = "admin " + host;
            //
        }
        
        if ( vulnType.compareTo( "DATA DISCLOSURE - INTEGRITY LOSS" ) == 0 )
        {
            admin = false;
            res = "data disclosure " + host;
        }
        if ( vulnType.compareTo( "DENIAL OF SERVICE" ) == 0 )
        {
            admin = false;
            res = "dos " + host;
        }
        if ( vulnType.compareTo( "INFORMATION DISCLOSURE" ) == 0 )
        {
            admin = false;
            res = "info " + host;
        }
        if ( vulnType.compareTo( "NETWORK INFO DISCLOSURE" ) == 0 )
        {
            admin = false;
            res = "net info " + host;
        }
        if ( vulnType.compareTo( "PURGE" ) == 0 )
        {
            admin = false;
            res = "purge " + host;
        }
        if ( vulnType.compareTo( "REMOTE CODE EXECUTION WITH USER PRIVILEGES" ) == 0 )
        {
            admin = false;
            res = "user " + host+ "- local " + host;
        }
        if ( vulnType.compareTo( "REMOTE TO LOCAL" ) == 0 )
        {
            admin = false;
            res = "local " + host;
        }
        if ( vulnType.compareTo( "SERVER WEB DISCLOSURE" ) == 0 )
        {
            admin = false;
            res = "server info " + host;
        }
        if ( vulnType.compareTo( "USER ENUMERATION" ) == 0 )
        {
            admin = false;
            res = "user enum " + host;
        }
        if ( vulnType.compareTo( "USER LOGIN GUESSABLE" ) == 0 )
        {
            admin = false;
            res = "user " + host + "- local " + host;
        }
        
        //inserisco i diritti per la tabella diritti
        if ( vulnType.compareTo( "USER LOGIN GUESSABLE" ) == 0 )
        {
            insertDiritto("user "+host, host);
            insertDiritto("local "+host , host);
        }
        else if ( vulnType.compareTo( "REMOTE CODE EXECUTION WITH USER PRIVILEGES" ) == 0 )
        {
            insertDiritto("user "+host, host);
            insertDiritto("local "+host , host);
        }
        else insertDiritto(res, host);
         res = res+"-";
        
        // Se l'attacco da diritti di admin allora alle postcondizioni già trovate
        // si aggiungono diritti di accesso a tutti gli host "x" per i quali esiste un collegamento
        // nella tabella enel.rights del tipo "host" -> "x"

        if ( admin == true )
        {
            insertDiritto( "data disclosure " + host, host );
            insertDiritto( "dos " + host, host );
            insertDiritto( "info " + host, host );
            insertDiritto( "net info " + host, host );
            insertDiritto( "purge " + host, host );
            insertDiritto( "user " + host, host );
            insertDiritto( "local " + host, host );
            insertDiritto( "server info " + host, host );
            insertDiritto( "user enum " + host, host );
            res = res + "data disclosure " + host + "-dos " + host + "-info " + host + "-net info " + host + "-purge " + host + "-user " + host + "-local " + host + "-server info " + host + "-user enum " + host + "-";
            for ( int r = 0; r < enelRights.size(); r++ )
            {
                String[] eRight = (String[])(enelRights.get(r));
                if ( host.compareTo( eRight[0] ) == 0 )
                {
                    res = res + "access " + traduciHost( eRight[1] )+"-";
                }
                else
                {
                    for ( int i = 0; i < specialHost.length; i++ )
                    {
                        if ( host.compareTo( specialHost[i] ) == 0 )
                        {
                            if ( specialInterface[i].compareTo( eRight[0] ) == 0 )
                            {
                                res = res + "access " + traduciHost( eRight[1] )+"-";
                                break;
                            }
                        }
                    }
                }
            }
        }
        return res;
    }
    
    /**
     * Restituisce le precondizioni dell'attacco dato il tipo di vulnerabilità che l'attacco sfrutta
     * e dato l'host che l'attacco insidia
     */
    private String getPreAtk(String vulnType, String host)
    {
        String res = "access " + host;
        
        //inserisco i diritti per la tabella diritti
        insertDiritto(res, host);
        
        if ( vulnType.compareTo( "LOCAL PRIVILEGES ESCALATION" ) == 0)
        {
            res = res + " -local " + host;
            //inserisco i diritti per la tabella diritti
            insertDiritto("local " + host, host);
        }
        return res+"-";
    }
    
    /**
     * Controlla se il parametro host è uno degli ip che non fa parte della tabella host:
     * se è così, restituisce l'indirizzo reale dell'host, usando le info nella tabella hostconnection,
     * altrimenti restituisce direttamente il parametro host (poichè questi è un vero indirizzo e non un'interfaccia)
     */
    public String traduciHost( String host )
    {
        for ( int i = 0; i < specialInterface.length; i++ )
        {
            if ( host.compareTo( specialInterface[i] ) == 0 )
            {
                return specialHost[i];
            }
        }
        return host;
    }
    
    /**
     * Calcola gli attacchi e li inserisce nel db vulsim
     */
    public void elaboraAttacchi()
    {
        ArrayList vulsimVuln = null;
        ArrayList vulsimComponenti = null;
        // Scarica dai db enel e vulsim_schema 4 tabelle utili per la computazione
        try
        {
            vulsimVuln = dbconVulsim.query( "vulnerabilita", "*", null );
            vulsimComponenti = dbconVulsim.query( "componente", "*", null );
            enelRights = dbconEnel.query( "rights", "interface, ifDest", null, "interface, ifDest" );
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        
        // Il vero e proprio calcolo e inserimento degli attacchi.
        // In GVScan non esiste una distinzione tra vulnerabilità e attacchi, quindi nel db di Haruspex
        // ad ogni vulnerabilità corrisponde alpiù un attacco.
        // Quindi, per ogni vulnerabilità in vulsim_schema.vulnerabilita...
        int idAtk = 1;
        ArrayList <String> precond = new ArrayList <String> ();
        ArrayList <String> postcond = new ArrayList <String> ();
        for ( int vv = 0; vv < vulsimVuln.size(); vv++ )
        {
            String[] vVuln = (String[])(vulsimVuln.get(vv));
            // Si scartano alcune vulnerabilità...
            if ( vVuln[2].compareTo( "Not classified" ) == 0 )
            {
                continue;
            }
            if ( vVuln[7].compareTo( "1" ) == 0 )
            {
                String idVuln = vVuln[0];
                String classVuln = vVuln[2];
                String livello = vVuln[6];
                String vProb = "0.4";
                if ( livello.compareTo( "basso" ) == 0 )
                {
                    vProb = "0.9";
                }
                if ( livello.compareTo( "medio" ) == 0 )
                {
                    vProb = "0.7";
                }
                if ( livello.compareTo( "alto" ) == 0 )
                {
                    vProb = "0.2";
                }
                String attacco = "atk " + vVuln[1];
                String host = "";
                // .. quindi si determina a quale componente la vulnerabilità presa in esame si riferisce...
                for ( int c = 0; c < vulsimComponenti.size(); c++ )
                {
                    String[] vComp = (String[])(vulsimComponenti.get(c));
                    if ( vVuln[4].compareTo( vComp[0] ) == 0 )
                    {
                        host = vComp[1];
                        break;
                    }
                }
                // .. quindi si calcolano pre/postcondizioni, port e protocol.
                int idEnelVuln = translateStringToNum( vVuln[8] );
                
                String precondiz = getPreAtk( classVuln, host );
                String postcondiz = getPostAtk( classVuln, host );
                int classe = precond.size();
                for ( int i = 0; i < precond.size(); i++ )
                {
                    if ( ( precondiz.compareTo( precond.get(i) ) == 0 ) 
                      && ( postcondiz.compareTo( postcond.get(i) ) == 0 ) )
                    {
                        classe = i;
                        break;
                    }
                }
                if ( classe == precond.size() )
                {
                    precond.add( precondiz );
                    postcond.add( postcondiz );
                }
                
                String[] eVuln = (String[])(enelVuln.get(idEnelVuln));
                // Infine si inserisce l'attacco nel db. 
                // Sfruttando inoltre il fatto che ad ogni attacco corrisponde forzatamente una singola vulnerabilità,
                // si può creare la relativa riga nella tabella vulsimschema.vulnattacco
                try
                {
                    String campo, valore;
                    campo = "id, nome, descrizione, precondizione, postcondizione, risorse, informazioni, rischio, prob_successo, class";
                    valore = "'" + idAtk + "' , '" + attacco + "' , '" + classVuln + "' , '" + precondiz + "' , '" + postcondiz + "' , 'basso' , 'basso' , 'basso' , " + vProb + " , " + classe;
                    dbconVulsim.insert( "attacco", campo, valore );
                    campo = "idAttacco, idVulnerabilita";
                    valore = "'" + idAtk + "' , '" + idVuln + "'";
                    dbconVulsim.insert( "vulnattacco", campo, valore );
                } catch (SQLException ex) {return;}
                idAtk++;
            }
        }
    }
    
    // </editor-fold> 
    
    // <editor-fold defaultstate="collapsed" desc="resetta"> 
    /**
     * Rsetta le tabelle in vulsim_schema
     */
    
    public void resettaSchema()
    {
       try
        {
            // Cancella il contenuto di tutte le tabelle di vulsim_schema...
            dbconVulsim.delete( "attacco" );
            dbconVulsim.delete( "componente" );
            dbconVulsim.delete( "diritto" );
            dbconVulsim.delete( "eventoattacco" );
            dbconVulsim.delete( "eventoobiettivo" );
            dbconVulsim.delete( "eventovulnerabilita" );
            dbconVulsim.delete( "groupsimulazione" );
            dbconVulsim.delete( "minaccia" );
            dbconVulsim.delete( "obiettivo" );
            dbconVulsim.delete( "simulazione" );
            dbconVulsim.delete( "sistema" );
            dbconVulsim.delete( "vulnattacco" );
            dbconVulsim.delete( "vulnerabilita" );
            dbconVulsim.delete( "subnetdistance" );
            dbconVulsim.delete( "typevuln" );
            // .. e inserisce un'unica riga nella tabella sistema
            String campo, valore;
            campo = "idSistema, nome, descrizione";
            valore = "'1' , '" + nomeSistema + "' , '" + descrizioneSistema + "'";
            dbconVulsim.insert( "sistema", campo, valore );
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
    }
    
    
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="minacce"> 
    /**
     * Elabora le minacce in vulsim_schema
     */
    
    public void elaboraMinacceObiettivi()
    {
        ArrayList vulsimHost = null;
        // Carica gli host presenti nella tabella enel.host...
        try
        {
            vulsimHost = dbconVulsim.query( "componente", "*", null );
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        
        int countMinaccia = 1;
        for ( int h = 0; h < vulsimHost.size(); h++ )
        {
            String[] vHost = (String[])(vulsimHost.get(h));
            boolean access = false;
            boolean admin = false;
            if ( minacceAccess[0].compareTo( "empty" ) != 0 )
            {
                if ( minacceAccess[0].compareTo( "all" ) == 0 )
                {
                    access = true;
                }
                else
                {
                    for ( int i = 0; i < minacceAccess.length; i++ )
                    {
                        if ( minacceAccess[i].compareTo( vHost[1] ) == 0 )
                        {
                            access = true;
                            break;
                        }
                    }
                }
            }
            if ( minacceAdmin[0].compareTo( "empty" ) != 0 )
            {
                if ( minacceAdmin[0].compareTo( "all" ) == 0 )
                {
                    admin = true;
                }
                else
                {
                    for ( int i = 0; i < minacceAdmin.length; i++ )
                    {
                        if ( minacceAdmin[i].compareTo( vHost[1] ) == 0 )
                        {
                            admin = true;
                            break;
                        }
                    }
                }
            }

            try
            {
                String campo, valore;
                if ( access == true )
                {
                    campo = "id, nome, dirittiIniziali, livelloRisorse, livelloInfAtk, livelloRischio, livelloInfVuln, lookahead";
                    valore = "'" + countMinaccia + "' , 'minaccia" + countMinaccia + "' , 'access " + vHost[1] + "-' , 'alto' , 'alto' , 'alto' , 'alto' , '1'";
                    dbconVulsim.insert( "minaccia", campo, valore );
                    
                    campo = "idObiettivo, nome, diritti, idMinaccia";
                    valore = "'" + countMinaccia + "' , 'obiettivo1' ," + obiettivo + " , '" + countMinaccia + "'";
                    dbconVulsim.insert( "obiettivo", campo, valore );
                    
                    countMinaccia++;
                }
                if ( admin == true )
                {
                    insertDiritto( "admin " + vHost[1], vHost[1] );
                    insertDiritto( "access " + vHost[1], vHost[1] );
                    /*insertDiritto( "data disclosure " + vHost[1], vHost[1] );
                    insertDiritto( "dos " + vHost[1], vHost[1] );
                    insertDiritto( "info " + vHost[1], vHost[1] );
                    insertDiritto( "net info " + vHost[1], vHost[1] );
                    insertDiritto( "purge " + vHost[1], vHost[1] );
                    insertDiritto( "user " + vHost[1], vHost[1] );
                    insertDiritto( "local " + vHost[1], vHost[1] );
                    insertDiritto( "server info " + vHost[1], vHost[1] );
                    insertDiritto( "user enum " + vHost[1], vHost[1] );*/
                    String diritti = "'access " + vHost[1] + "-admin " + vHost[1];
                    //diritti = diritti + "-data disclosure " + vHost[1] + "-dos " + vHost[1] + "-info " + vHost[1] + "-net info " + vHost[1] + "-purge " + vHost[1] + "-user " + vHost[1] + "-local " + vHost[1] + "-server info " + vHost[1] + "-user enum " + vHost[1] ;

                    for ( int r = 0; r < enelRights.size(); r++ )
                    {
                        String[] eRight = (String[])(enelRights.get(r));
                        if ( vHost[1].compareTo( eRight[0] ) == 0 )
                        {
                            diritti = diritti + "-access " + traduciHost( eRight[1] );
                            insertDiritto( "access " + traduciHost( eRight[1] ), traduciHost( eRight[1] ) );
                        }
                        else
                        {
                            for ( int i = 0; i < specialHost.length; i++ )
                            {
                                if ( vHost[1].compareTo( specialHost[i] ) == 0 )
                                {
                                    if ( specialInterface[i].compareTo( eRight[0] ) == 0 )
                                    {
                                        diritti = diritti + "-access " + traduciHost( eRight[1] );
                                        insertDiritto( "access " + traduciHost( eRight[1] ), traduciHost( eRight[1] ) );
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    
                    campo = "id, nome, dirittiIniziali, livelloRisorse, livelloInfAtk, livelloRischio, livelloInfVuln, lookahead";
                    valore = "'" + countMinaccia + "' , 'minaccia" + countMinaccia + "' , " + diritti + "-' , 'alto' , 'alto' , 'alto' , 'alto' , '1'";
                    dbconVulsim.insert( "minaccia", campo, valore );

                    campo = "idObiettivo, nome, diritti, idMinaccia";
                    valore = "'" + countMinaccia + "' , 'obiettivo1' ," + obiettivo + " , '" + countMinaccia + "'";
                    dbconVulsim.insert( "obiettivo", campo, valore );
                    
                    countMinaccia++;
                }
            } catch (SQLException ex) {return;}
        }
    }
    
    
    
    // </editor-fold>
    
    
    // <editor-fold defaultstate="collapsed" desc="vulnerabilità">  
            
    /**
     * Trova le vulnerabilità di enel e li inserisce nel db vulsim
     */
    public void elaboraVulnerabilità()
    {
      //ArrayList oVuln=null;
        enelVuln=null;
        try 
        {
            enelVuln = dbconEnel.query("vulnerability","*", null);
        } catch (SQLException ex) { Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex); }
        for( int i = 0; i < enelVuln.size(); i++ )
        {
            insertVulnerabilitàVulsim((String[])enelVuln.get(i));
        }    
   }

    private void insertVulnerabilitàVulsim(String[] vuln) 
    {
        //nomi campi
        String nome = "nome";
        String descrizione = "descrizione";
        String idVulsim = "idVulnerabilita";
        String probabilita = "probabilita";
        String idComponente = "idComponente";
        String livello = "livello";
        String avaible = "avaible";
        String gvScanRef = "typeVuln";
        
        //valori campi da inserire nel database
        int vId;
        String vNome = vuln[1];
        String vDescrizione = formatName(vuln[5]);
        if(vDescrizione==null) vDescrizione = "";
        String vLivello = formatName("unknown");
        String vProbabilita = formatName("1");
        int vGvScanRef = translateStringToNum(vuln[0]);
        
        if ( vuln[15] != null )
        {
            if ( vuln[15].compareTo( "Low" ) == 0 )
            {
                vLivello = formatName("basso");
            }
            if ( vuln[15].compareTo( "Medium" ) == 0 )
            {
                vLivello = formatName("medio");
            }
            if ( vuln[15].compareTo( "High" ) == 0 )
            {
                vLivello = formatName("alto");
            }
        }
        
        //calcolo tutti i componenti che sono affetti
        ArrayList hostList=null;
        try 
        {    
            hostList = dbconEnel.query("hostVuln", "host", "vulnerability="+vuln[0]+" group by host");
        } catch (SQLException ex) {Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        
        for(int i=0; i<hostList.size();i++)
        {
              //controllo sull'esistenza della vuln. se c'è gia non lo inserisco
            if(!dbconVulsim.existElement("vulnerabilita", "nome="+formatName(vNome+ "#" +((String[])hostList.get(i))[0] )+" AND avaible=1"))
            {
                int vIdComponente = -1;
                try 
                {
                    String nameHost = ((String[])hostList.get(i))[0] ;
                    String [] strArrayIdComponente = (String[])dbconVulsim.query("componente", "idComponente", "nome="+formatName(nameHost)).get(0);

                    vIdComponente = translateStringToNum(strArrayIdComponente[0]); 

                    //guardo se la vulnerabilità può essere sfruttata
                    Boolean vAvaible = checkAvaible(vGvScanRef,nameHost);

                    vId = dbconVulsim.getMaxId("vulnerabilita",idVulsim)+1;

                    //creo stringhe per la query nel database
                    String valore;
                    String campo;

                    valore = formatName(vNome+ "#" +((String[])hostList.get(i))[0])+" , "+vId+" , "+vLivello+" , "+vProbabilita+" , "+vIdComponente+" , "+vAvaible+" , "+vGvScanRef;
                    campo = nome+" , "+ idVulsim+" , "+livello+" , "+probabilita+" , "+idComponente+" , "+avaible+" , "+gvScanRef;

                   //in caso di campi null non li inserisco
                    if(vDescrizione!=null)
                    {
                        valore = valore +" , "+vDescrizione;
                        campo = campo +" , "+descrizione;
                    }

                    dbconVulsim.insert("vulnerabilita", campo, valore);
                    
                    
                } catch (SQLException ex) {return;}
            }
        }
        try
        {
            String valore = vGvScanRef + " , ";
            if ( vuln[2] == null )
            {
                valore = valore + formatName( vuln[1] + " (id = " + vuln[0] + ")" );
            }
            else
            {
                valore = valore + formatName( vuln[2] );
            }
            String campo = "id , description";
            dbconVulsim.insert("typevuln", campo, valore);
        } catch (SQLException ex) {return;}
    }
        
    
   // </editor-fold>   

    /**
     * Controlla che la vunerabilità posso essere sfruttata
     * @param vNome nome della vulnerabilità
     * @param idComponente id del componente
     * @return 
     */
    private Boolean checkAvaible(int idEnelVuln, String nomeHost) 
    {
        try 
        {
            ArrayList protocol = dbconEnel.query("vulnerability", "protocol, port", "id ="+idEnelVuln);
            String protocolVuln = ((String[])protocol.get(0))[0];
            int portVuln = translateStringToNum(((String[])protocol.get(0))[1]);
            
            boolean esiste = dbconEnel.existElement("rights", "ifDest="+formatName(nomeHost)+" and portDest="+portVuln+" and protocolDest="+formatName(protocolVuln));
            if ( esiste == false )
            {
                for ( int i = 0; i < specialHost.length; i++ )
                {
                    if ( specialHost[i].compareTo( nomeHost ) == 0 )
                    {
                        esiste = dbconEnel.existElement("rights", "ifDest="+formatName( specialInterface[i] )+" and portDest="+portVuln+" and protocolDest="+formatName(protocolVuln));
                        if ( esiste == true )
                        {
                            break;
                        }
                    }
                }
            }            
            return esiste;
            
        } catch (SQLException ex) { Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex); }
        return false;
    }
    
    
     // <editor-fold defaultstate="collapsed" desc="diritti"> 
    
    /**
     * Inserisce i diritti trovati nella lista dei possibili diritti.
     * Se i diritti esistono gia non li inserisce
     * @param diritto
     * @param host 
     */
    private void insertDiritto(String diritto, String host)
    {
        for ( int i = 0; i < dirittiList.size(); i++ )
        {
            if ( dirittiList.get(i).compareTo( diritto ) == 0 )
            {
                if ( hostDirittiList.get(i).compareTo( host ) == 0 ) 
                {
                    return;
                }
            }
        }
        dirittiList.add( diritto );
        hostDirittiList.add( host );
    }
 
    /**
     * inserisco i diritti nel database
     */
    public void elaboraDiritti()
    {
        String valore;
        String campo;
        //nomi campi
        String id = "id";
        String componente = "componente";
        String idComponente = "idComponente";
        String operazione = "operazione";
        for( int i=0; i<dirittiList.size(); i++ )
        {
            //creo stringhe per la query nel database
            try 
            {
                ArrayList h = dbconVulsim.query( "componente", "idComponente", "nome = '" + hostDirittiList.get(i) + "'" );
                String[] s = (String[])(h.get(0));
                valore = formatName(hostDirittiList.get(i))+" , "+i+" , "+formatName(dirittiList.get(i)) + " , " + s[0];
                campo = componente+" , "+ id+" , "+operazione + " , " + idComponente;
                dbconVulsim.insert("diritto", campo, valore);
            } catch (SQLException ex) { Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex);}
        }
    }
    
     // </editor-fold> 
    
    public void elaboraRouting()
    {
        int[][] distance;
        try
        {
            ArrayList rSubnets = dbconVulsim.query("componente", "subnet", "idComponente >= -1 group by subnet");
            ArrayList rComponenti = dbconVulsim.query("componente", "nome, subnet", null);
            ArrayList rAttacchi = dbconVulsim.query("attacco", "precondizione, postcondizione", null);
            distance = new int[ rSubnets.size() ][ rSubnets.size() ];            
            for ( int i = 0; i < rSubnets.size(); i++ )
            {
                for ( int j = 0; j < rSubnets.size(); j++ )
                {
                    if ( i == j )
                    {
                        distance[i][i] = 0;
                    }
                    else
                    {
                        distance[i][j] = -1;
                    }
                }
            }
            
            // Calcola i collegamenti diretti
            ArrayList <String> componenti = new ArrayList <String>();
            ArrayList <String> sottoretiComp = new ArrayList <String>();
            ArrayList <String> sottoreti = new ArrayList <String>();
            for ( int i = 0; i < rSubnets.size(); i++ )
            {
                String[] s = (String[])(rSubnets.get(i));
                sottoreti.add( s[0] );
            }
            for ( int i = 0; i < rComponenti.size(); i++ )
            {
                String[] s = (String[])(rComponenti.get(i));
                componenti.add( s[0] );
                sottoretiComp.add( s[1] );
            }
            for ( int a = 0; a < rAttacchi.size(); a++ )
            {
                String[] s = (String[])(rAttacchi.get(a));
                String comp = s[0].substring(7);
                String[] ss = comp.split("-");
                comp = ss[0];
                int c = 0;
                while ( comp.compareTo( componenti.get(c) ) != 0 )
                {
                    c++;
                }
                int subPartenza = 0;
                while ( sottoretiComp.get(c).compareTo( sottoreti.get(subPartenza) ) != 0 )
                {
                    subPartenza++;
                }
                String[] postc = s[1].split("-");
                for ( int p = 0; p < postc.length; p++ )
                {
                    ss = postc[p].split(" ");
                    if ( ss[0].compareTo("access") == 0 )
                    {
                        c = 0;
                        while ( ss[1].compareTo( componenti.get(c) ) != 0 )
                        {
                            c++;
                        }
                        int sub = 0;
                        while ( sottoretiComp.get(c).compareTo( sottoreti.get(sub) ) != 0 )
                        {
                            sub++;
                        }
                        if ( subPartenza != sub )
                        {
                            distance[subPartenza][sub] = 1;
                        }
                    }
                }
            }
            
            // Calcola lunghezza cammini complessi
            ArrayList <Link> links = new ArrayList <Link>();
            for ( int i = 0; i < rSubnets.size(); i++ )
            {
                for ( int j = 0; j < rSubnets.size(); j++ )
                {
                    if ( distance[i][j] == 1 )
                    {
                        Link link = new Link();
                        link.sub1 = i;
                        link.sub2 = j;
                        links.add( link);
                    }
                }
            }
            int k = 1;
            while ( true )
            {
                boolean added = false;
                for ( int i = 0; i < rSubnets.size(); i++ )
                {
                    for ( int j = 0; j < rSubnets.size(); j++ )
                    { 
                        if ( distance[i][j] == k )
                        {
                            // Aggiungere in testa
                            for ( int l = 0; l < links.size(); l++ )
                            {
                                if ( ( links.get(l).sub1 != j ) && ( links.get(l).sub2 == i ) )
                                {
                                    if ( distance[ links.get(l).sub1 ][ j ] == -1 )
                                    {
                                        added = true;
                                        distance[ links.get(l).sub1 ][ j ] = k + 1;
                                    }
                                    else
                                    {
                                        if ( k + 1 < distance[ links.get(l).sub1 ][ j ] )
                                        {
                                            added = true;
                                            distance[ links.get(l).sub1 ][ j ] = k + 1;
                                        }
                                    }
                                    
                                }
                            }
                            // Aggiungere in coda
                            for ( int l = 0; l < links.size(); l++ )
                            {
                                if ( ( links.get(l).sub1 == j ) && ( links.get(l).sub2 != i ) )
                                {
                                    if ( distance[ i ][ links.get(l).sub2 ] == -1 )
                                    {
                                        added = true;
                                        distance[ i ][ links.get(l).sub2 ] = k + 1;
                                    }
                                    else
                                    {
                                        if ( k + 1 < distance[ i ][ links.get(l).sub2 ] )
                                        {
                                            added = true;
                                            distance[ i ][ links.get(l).sub2 ] = k + 1;
                                        }
                                    }
                                    
                                }
                            }
                        }
                    }
                }
                if ( added == true )
                {
                    k++;
                }
                else
                {
                    break;
                }
            }
            for ( int i = 0; i < rSubnets.size(); i++ )
            {
                for ( int j = 0; j < rSubnets.size(); j++ )
                { 
                    if ( distance[i][j] > 0 )
                    {
                        dbconVulsim.insert( "subnetdistance", "subnet1 , subnet2 , distance", "'" + sottoreti.get(i) + "' , '" + sottoreti.get(j) + "' , " + distance[i][j] );
                    }
                }
            }
        } catch (SQLException ex) { Logger.getLogger(Procedure.class.getName()).log(Level.SEVERE, null, ex); }
    }
    
}
